package com.cinema.controller;

import com.cinema.model.Admin;
import com.cinema.model.User;
import com.cinema.service.UserService;
import com.cinema.util.Constants;
import com.cinema.model.UserType;
import com.cinema.model.Manager;
import com.cinema.model.FrontDesk;
import com.cinema.service.LogService;
import com.cinema.model.Movie;
import com.cinema.model.Schedule;
import com.cinema.service.MovieService;
import com.cinema.service.ScheduleService;
import com.cinema.service.TicketService;
import com.cinema.service.HallService;
import com.cinema.util.InMemoryBootstrap;

import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.stream.Collectors;

/**
 * 主控制器类
 * 
 * @author Cinema Management System
 * @version 1.0.0
 */
public class MainController {
    
    private final UserService userService;
    private final Scanner scanner;
    private User currentUser;
    private final LogService logService;
    private final MovieService movieService;
    private final ScheduleService scheduleService;
    private final TicketService ticketService;
    private final HallService hallService;
    
    /**
     * 构造函数
     */
    public MainController() {
        this.userService = new UserService();
        this.scanner = new Scanner(System.in);
        this.logService = new LogService();
        this.scheduleService = new ScheduleService();
        this.movieService = new MovieService(scheduleService);
        this.hallService = new HallService();
        this.ticketService = new TicketService(hallService, scheduleService);
        initializeSystem();
    }
    
    /**
     * 启动系统
     */
    public void start() {
        try {
            while (true) {
                if (currentUser == null) {
                    showMainMenu();
                } else {
                    showUserMenu();
                }
            }
        } catch (Exception e) {
            System.err.println("系统运行异常：" + e.getMessage());
            e.printStackTrace();
        } finally {
            scanner.close();
        }
    }
    
    /**
     * 初始化系统
     */
    private void initializeSystem() {
        try {
            // 初始化默认管理员/经理/前台账户
            userService.initializeDefaultAdmin();
            userService.initializeDefaultManager();
            userService.initializeDefaultFrontDesk();
            // 初始化内存中的影片与场次数据
            InMemoryBootstrap.seed(movieService, scheduleService);
            System.out.println("系统初始化完成！");
            System.out.println();
        } catch (Exception e) {
            System.err.println("系统初始化失败：" + e.getMessage());
            throw new RuntimeException("系统初始化失败", e);
        }
    }
    
    /**
     * 显示主菜单
     */
    private void showMainMenu() {
        System.out.println(Constants.SEPARATOR_LINE);
        System.out.println("                    主菜单");
        System.out.println(Constants.SEPARATOR_LINE);
        System.out.println("1. 用户登录");
        System.out.println("0. 退出系统");
        System.out.println(Constants.SHORT_SEPARATOR_LINE);
        System.out.print("请选择操作：");
        
        String choice = scanner.nextLine().trim();
        
        switch (choice) {
            case "1":
                handleLogin();
                break;
            case "0":
                System.out.println("感谢使用" + Constants.SYSTEM_NAME + "，再见！");
                System.exit(0);
                break;
            default:
                System.out.println(Constants.INVALID_INPUT);
                break;
        }
    }
    
    /**
     * 显示用户菜单
     */
    private void showUserMenu() {
        System.out.println(Constants.SEPARATOR_LINE);
        System.out.println("当前用户：" + currentUser.getUsername() + " (" + currentUser.getUserType().getDisplayName() + ")");
        System.out.println(Constants.SEPARATOR_LINE);
        
        switch (currentUser.getUserType()) {
            case ADMIN:
                showAdminMenu();
                break;
            case MANAGER:
                showManagerMenu();
                break;
            case FRONT_DESK:
                showFrontDeskMenu();
                break;
        }
    }
    
    /**
     * 显示管理员菜单
     */
    private void showAdminMenu() {
        System.out.println("1. 密码管理");
        System.out.println("2. 用户管理");
        System.out.println("0. 退出登录");
        System.out.println(Constants.SHORT_SEPARATOR_LINE);
        System.out.print("请选择操作：");
        
        String choice = scanner.nextLine().trim();
        
        switch (choice) {
            case "1":
                handlePasswordManagement();
                break;
            case "2":
                handleUserManagement();
                break;
            case "0":
                handleLogout();
                break;
            default:
                System.out.println(Constants.INVALID_INPUT);
                break;
        }
    }
    
    /**
     * 显示经理菜单
     */
    private void showManagerMenu() {
        System.out.println("1. 密码管理");
        System.out.println("2. 影片管理");
        System.out.println("3. 排片管理");
        System.out.println("4. 查看销售数据");
        System.out.println("0. 退出登录");
        System.out.println(Constants.SHORT_SEPARATOR_LINE);
        System.out.print("请选择操作：");
        
        String choice = scanner.nextLine().trim();
        
        switch (choice) {
            case "1":
                handlePasswordManagement();
                break;
            case "2":
                handleMovieManagement();
                break;
            case "3":
                handleScheduleManagement();
                break;
            case "4":
                handleSalesDataView();
                break;
            case "0":
                handleLogout();
                break;
            default:
                System.out.println(Constants.INVALID_INPUT);
                break;
        }
    }
    
    /**
     * 显示前台菜单
     */
    private void showFrontDeskMenu() {
        System.out.println("1. 查看影片信息");
        System.out.println("2. 查看场次信息");
        System.out.println("3. 查看指定电影与场次的座位信息");
        System.out.println("4. 售票");
        System.out.println("5. 退票");
        System.out.println("0. 退出登录");
        System.out.println(Constants.SHORT_SEPARATOR_LINE);
        System.out.print("请选择操作：");
        
        String choice = scanner.nextLine().trim();
        
        switch (choice) {
            case "1":
                handleMovieInfoView();
                break;
            case "2":
                handleScheduleInfoView();
                break;
            case "3":
                handleSeatMapView();
                break;
            case "4":
                handleTicketSale();
                break;
            case "5":
                handleTicketRefund();
                break;
            case "0":
                handleLogout();
                break;
            default:
                System.out.println(Constants.INVALID_INPUT);
                break;
        }
    }
    
    /**
     * 处理用户登录
     */
    private void handleLogin() {
        System.out.println(Constants.SHORT_SEPARATOR_LINE);
        System.out.println("                    用户登录");
        System.out.println(Constants.SHORT_SEPARATOR_LINE);
        
        System.out.print("请输入用户名：");
        String username = scanner.nextLine().trim();
        
        System.out.print("请输入密码：");
        String password = scanner.nextLine().trim();
        
        try {
            currentUser = userService.login(username, password);
            System.out.println(Constants.LOGIN_SUCCESS);
            System.out.println();
            // 登录后若标记需改密，强制修改密码
            if (currentUser.isNeedChangePassword()) {
                System.out.println("检测到首次登录或已被重置密码，需立即修改密码。");
                while (true) {
                    System.out.print("请输入新密码：");
                    String newPwd = scanner.nextLine().trim();
                    if (newPwd == null || newPwd.isEmpty()) {
                        System.out.println("新密码不能为空");
                        continue;
                    }
                    currentUser.changePassword(newPwd);
                    userService.updateUser(currentUser);
                    if (currentUser.getUserType() == UserType.ADMIN) {
                        logService.writeLog("修改管理员密码", currentUser.getUsername(), "自助修改密码");
                    }
                    System.out.println(Constants.PASSWORD_CHANGED);
                    break;
                }
            }
        } catch (Exception e) {
            System.out.println("登录失败：" + e.getMessage());
            System.out.println();
        }
    }
    
    /**
     * 处理退出登录
     */
    private void handleLogout() {
        currentUser = null;
        System.out.println(Constants.LOGOUT_SUCCESS);
        System.out.println();
    }
    
    /**
     * 处理密码管理
     */
    private void handlePasswordManagement() {
        if (currentUser == null) {
            System.out.println(Constants.PERMISSION_DENIED);
            return;
        }
        System.out.println(Constants.SHORT_SEPARATOR_LINE);
        System.out.println("                密码管理");
        System.out.println(Constants.SHORT_SEPARATOR_LINE);
        System.out.println("1. 修改自身密码");
        if (currentUser.getUserType() == UserType.ADMIN || currentUser.getUserType() == UserType.MANAGER) {
            System.out.println("2. 重置用户密码");
        }
        System.out.println("0. 返回上级菜单");
        System.out.print("请选择操作：");
        String choice = scanner.nextLine().trim();
        if ("1".equals(choice)) {
            System.out.print("请输入旧密码：");
            String oldPwd = scanner.nextLine().trim();
            System.out.print("请输入新密码：");
            String newPwd = scanner.nextLine().trim();
            try {
                userService.changeUserPassword(currentUser.getUsername(), oldPwd, newPwd);
                if (currentUser.getUserType() == UserType.ADMIN) {
                    logService.writeLog("修改管理员密码", currentUser.getUsername(), "自助修改密码");
                }
                System.out.println(Constants.PASSWORD_CHANGED);
            } catch (Exception e) {
                System.out.println(Constants.OPERATION_FAILED + ": " + e.getMessage());
            }
            System.out.println();
            return;
        }
        if ("2".equals(choice) && (currentUser.getUserType() == UserType.ADMIN || currentUser.getUserType() == UserType.MANAGER)) {
            System.out.print("请输入需要重置密码的用户名：");
            String uname = scanner.nextLine().trim();
            User target = userService.findUserByUsername(uname);
            if (target == null) {
                System.out.println("用户不存在");
                System.out.println();
                return;
            }
            if (currentUser.getUserType() == UserType.MANAGER && target.getUserType() != UserType.FRONT_DESK) {
                System.out.println("经理仅能重置前台用户的密码");
                System.out.println();
                return;
            }
            if (currentUser.getUserType() == UserType.ADMIN && target.getUserType() == UserType.ADMIN && Constants.DEFAULT_ADMIN_USERNAME.equals(uname)) {
                System.out.println("不允许重置默认管理员的密码");
                System.out.println();
                return;
            }
            try {
                userService.resetUserPassword(uname);
                String typeLabel = target.getUserType() == UserType.ADMIN ? "管理员" : (target.getUserType() == UserType.MANAGER ? "经理" : "前台");
                String op = (currentUser.getUserType() == UserType.MANAGER) ? ("重置前台" + uname + " 的密码") : ("重置" + typeLabel + " " + uname + " 的密码");
                logService.writeLog(op, currentUser.getUsername(), "重置为默认密码");
                System.out.println("已重置为默认密码：" + Constants.DEFAULT_PASSWORD + "，用户下次登录需修改密码。");
            } catch (Exception e) {
                System.out.println(Constants.OPERATION_FAILED + ": " + e.getMessage());
            }
        System.out.println();
        }
    }
    
    /**
     * 处理用户管理（管理员专用）
     */
    private void handleUserManagement() {
        if (currentUser == null || currentUser.getUserType() != UserType.ADMIN) {
            System.out.println(Constants.PERMISSION_DENIED);
            return;
        }
        while (true) {
            System.out.println(Constants.SHORT_SEPARATOR_LINE);
            System.out.println("                用户管理");
            System.out.println(Constants.SHORT_SEPARATOR_LINE);
            System.out.println("1. 列出所有用户（经理、前台）");
            System.out.println("2. 删除指定用户");
            System.out.println("3. 查询用户信息（按ID/用户名/全部）");
            System.out.println("4. 增加用户（管理员/经理/前台）");
            System.out.println("5. 修改用户（经理/前台）信息");
            System.out.println("0. 返回上级菜单");
            System.out.print("请选择操作：");
            String choice = scanner.nextLine().trim();
            switch (choice) {
                case "1":
                    listNonAdminUsers();
                    break;
                case "2":
                    deleteUserFlow();
                    break;
                case "3":
                    queryUserFlow();
                    break;
                case "4":
                    addUserFlow();
                    break;
                case "5":
                    modifyUserFlow();
                    break;
                case "0":
                    return;
                default:
                    System.out.println(Constants.INVALID_INPUT);
            }
        }
    }
    
    private void listNonAdminUsers() {
        List<User> all = userService.getAllUsers();
        System.out.println("用户列表（经理/前台）：");
        for (User u : all) {
            if (u.getUserType() != UserType.ADMIN) {
                printUserSummary(u);
            }
        }
        System.out.println();
    }
    
    private void deleteUserFlow() {
        System.out.print("请输入要删除的用户名：");
        String uname = scanner.nextLine().trim();
        User u = userService.findUserByUsername(uname);
        if (u == null) {
            System.out.println("用户不存在");
            System.out.println();
            return;
        }
        System.out.println("警告：删除后不可恢复！");
        System.out.print("确认删除用户 " + uname + "? 输入Y确认：");
        String confirm = scanner.nextLine().trim();
        if (!"Y".equalsIgnoreCase(confirm)) {
            System.out.println("已取消删除操作");
            System.out.println();
            return;
        }
        try {
            userService.deleteUser(uname);
            String typeLabel = u.getUserType() == UserType.ADMIN ? "管理员" : (u.getUserType() == UserType.MANAGER ? "经理" : "前台");
            logService.writeLog("删除" + typeLabel + " " + uname, currentUser.getUsername(), "用户ID=" + u.getUserId());
            System.out.println(Constants.USER_DELETED);
        } catch (Exception e) {
            System.out.println(Constants.OPERATION_FAILED + ": " + e.getMessage());
        }
        System.out.println();
    }
    
    private void queryUserFlow() {
        System.out.println("1. 按用户ID查询");
        System.out.println("2. 按用户名查询");
        System.out.println("3. 查询全部");
        System.out.print("请选择：");
        String c = scanner.nextLine().trim();
        switch (c) {
            case "1":
                System.out.print("请输入用户ID：");
                String uid = scanner.nextLine().trim();
                User byId = userService.findUserById(uid);
                if (byId == null) {
                    System.out.println("未找到用户");
                } else {
                    printUserSummary(byId);
                }
                break;
            case "2":
                System.out.print("请输入用户名：");
                String uname = scanner.nextLine().trim();
                User byName = userService.findUserByUsername(uname);
                if (byName == null) {
                    System.out.println("未找到用户");
                } else {
                    printUserSummary(byName);
                }
                break;
            case "3":
                for (User u : userService.getAllUsers()) {
                    printUserSummary(u);
                }
                break;
            default:
                System.out.println(Constants.INVALID_INPUT);
        }
        System.out.println();
    }
    
    private void addUserFlow() {
        System.out.println("选择用户类型：1-管理员  2-经理  3-前台");
        System.out.print("请输入：");
        String t = scanner.nextLine().trim();
        UserType type;
        if ("1".equals(t)) {
            type = UserType.ADMIN;
        } else if ("2".equals(t)) {
            type = UserType.MANAGER;
        } else if ("3".equals(t)) {
            type = UserType.FRONT_DESK;
        } else {
            System.out.println(Constants.INVALID_INPUT);
            System.out.println();
            return;
        }
        System.out.print("用户ID：");
        String userId = scanner.nextLine().trim();
        System.out.print("用户名：");
        String username = scanner.nextLine().trim();
        System.out.print("手机号：");
        String phone = scanner.nextLine().trim();
        try {
            User newUser;
            String defaultPwd = Constants.DEFAULT_PASSWORD;
            if (type == UserType.ADMIN) {
                newUser = new Admin(userId, username, defaultPwd, phone);
            } else if (type == UserType.MANAGER) {
                newUser = new Manager(userId, username, defaultPwd, phone);
            } else {
                newUser = new FrontDesk(userId, username, defaultPwd, phone);
            }
            newUser.setNeedChangePassword(true);
            userService.addUser(newUser);
            String typeLabel = type == UserType.ADMIN ? "管理员" : (type == UserType.MANAGER ? "经理" : "前台");
            logService.writeLog("增加" + typeLabel + " " + username, currentUser.getUsername(), "用户ID=" + userId);
            System.out.println(Constants.USER_ADDED + "。默认密码：" + defaultPwd + "，登录后需修改。");
        } catch (Exception e) {
            System.out.println(Constants.OPERATION_FAILED + ": " + e.getMessage());
        }
        System.out.println();
    }
    
    private void modifyUserFlow() {
        System.out.print("请输入要修改的用户名（仅限经理/前台）：");
        String uname = scanner.nextLine().trim();
        User u = userService.findUserByUsername(uname);
        if (u == null) {
            System.out.println("用户不存在");
            System.out.println();
            return;
        }
        if (u.getUserType() == UserType.ADMIN) {
            System.out.println("仅允许修改经理/前台的信息");
            System.out.println();
            return;
        }
        System.out.println("1. 修改用户类型（经理/前台）");
        System.out.println("2. 修改手机号");
        System.out.print("请选择：");
        String c = scanner.nextLine().trim();
        try {
            if ("1".equals(c)) {
                System.out.print("选择新类型：1-经理  2-前台：");
                String nt = scanner.nextLine().trim();
                UserType newType = "1".equals(nt) ? UserType.MANAGER : ("2".equals(nt) ? UserType.FRONT_DESK : null);
                userService.changeUserType(uname, newType);
                System.out.println(Constants.USER_UPDATED);
            } else if ("2".equals(c)) {
                System.out.print("输入新手机号：");
                String np = scanner.nextLine().trim();
                userService.updateUserPhone(uname, np);
                System.out.println(Constants.USER_UPDATED);
            } else {
                System.out.println(Constants.INVALID_INPUT);
            }
        } catch (Exception e) {
            System.out.println(Constants.OPERATION_FAILED + ": " + e.getMessage());
        }
        System.out.println();
    }
    
    private void printUserSummary(User u) {
        System.out.println("[" + u.getUserType().getDisplayName() + "] ID=" + u.getUserId() + ", 用户名=" + u.getUsername() + ", 注册时间=" + u.getRegisterTime() + ", 手机号=" + u.getPhoneNumber());
    }
    
    /**
     * 处理影片管理
     */
    private void handleMovieManagement() {
        while (true) {
            System.out.println(Constants.SHORT_SEPARATOR_LINE);
            System.out.println("                影片管理");
            System.out.println(Constants.SHORT_SEPARATOR_LINE);
            System.out.println("1. 列出所有正在上映影片");
            System.out.println("2. 添加影片");
            System.out.println("3. 修改影片");
            System.out.println("4. 删除影片");
            System.out.println("5. 查询影片（按片名/导演/主演，支持组合）");
            System.out.println("0. 返回上级菜单");
            System.out.print("请选择操作：");
            String choice = scanner.nextLine().trim();
            try {
                switch (choice) {
                    case "1":
                        List<Movie> showing = movieService.listShowing();
                        if (showing.isEmpty()) System.out.println("暂无正在上映影片");
                        for (Movie m : showing) printMovieSummary(m);
                        break;
                    case "2":
                        addMovieFlow();
                        break;
                    case "3":
                        modifyMovieFlow();
                        break;
                    case "4":
                        deleteMovieFlow();
                        break;
                    case "5":
                        queryMovieFlow();
                        break;
                    case "0":
                        return;
                    default:
                        System.out.println(Constants.INVALID_INPUT);
                }
            } catch (Exception e) {
                System.out.println(Constants.OPERATION_FAILED + ": " + e.getMessage());
            }
        System.out.println();
        }
    }
    
    private void addMovieFlow() {
        System.out.print("电影ID：");
        String movieId = scanner.nextLine().trim();
        System.out.print("片名：");
        String title = scanner.nextLine().trim();
        System.out.print("导演：");
        String director = scanner.nextLine().trim();
        System.out.print("主演：");
        String actors = scanner.nextLine().trim();
        System.out.print("剧情简介：");
        String desc = scanner.nextLine().trim();
        System.out.print("时长（分钟）：");
        int duration = parseInt(scanner.nextLine().trim(), "时长应为正整数");
        System.out.print("评分（0-10）：");
        double rating = parseDouble(scanner.nextLine().trim(), "评分应为数字");
        Movie m = new Movie(movieId, title, director, actors, desc, duration, rating);
        movieService.addMovie(m);
        System.out.println(Constants.MOVIE_ADDED);
    }
    
    private void modifyMovieFlow() {
        System.out.print("请输入待修改的电影ID：");
        String movieId = scanner.nextLine().trim();
        Movie existing = movieService.findById(movieId);
        if (existing == null) {
            System.out.println("电影不存在");
            return;
        }
        System.out.print("片名（留空不改）：");
        String title = scanner.nextLine();
        if (!title.trim().isEmpty()) existing.setTitle(title.trim());
        System.out.print("导演（留空不改）：");
        String director = scanner.nextLine();
        if (!director.trim().isEmpty()) existing.setDirector(director.trim());
        System.out.print("主演（留空不改）：");
        String actors = scanner.nextLine();
        if (!actors.trim().isEmpty()) existing.setActors(actors.trim());
        System.out.print("剧情简介（留空不改）：");
        String desc = scanner.nextLine();
        if (!desc.trim().isEmpty()) existing.setDescription(desc.trim());
        System.out.print("时长（分钟，留空不改）：");
        String durStr = scanner.nextLine();
        if (!durStr.trim().isEmpty()) existing.setDuration(parseInt(durStr.trim(), "时长应为正整数"));
        System.out.print("评分（0-10，留空不改）：");
        String ratingStr = scanner.nextLine();
        if (!ratingStr.trim().isEmpty()) existing.setRating(parseDouble(ratingStr.trim(), "评分应为数字"));
        movieService.updateMovie(existing);
        System.out.println(Constants.MOVIE_UPDATED);
    }
    
    private void deleteMovieFlow() {
        System.out.print("请输入要删除的电影ID：");
        String movieId = scanner.nextLine().trim();
        Movie existing = movieService.findById(movieId);
        if (existing == null) {
            System.out.println("电影不存在");
            return;
        }
        System.out.println("警告：删除后无法恢复！");
        System.out.print("确认删除影片 '" + existing.getTitle() + "'? 输入Y确认：");
        String c = scanner.nextLine().trim();
        if (!"Y".equalsIgnoreCase(c)) {
            System.out.println("已取消删除");
            return;
        }
        movieService.deleteMovie(movieId);
        System.out.println(Constants.MOVIE_DELETED);
    }
    
    private void queryMovieFlow() {
        System.out.print("片名（可留空）：");
        String title = scanner.nextLine();
        System.out.print("导演（可留空）：");
        String director = scanner.nextLine();
        System.out.print("主演（可留空）：");
        String actors = scanner.nextLine();
        List<Movie> result = movieService.query(emptyToNull(title), emptyToNull(director), emptyToNull(actors));
        if (result.isEmpty()) System.out.println("未找到符合条件的影片");
        for (Movie m : result) printMovieSummary(m);
    }
    
    private void printMovieSummary(Movie m) {
        System.out.println("片名=" + m.getTitle() + ", 导演=" + m.getDirector() + ", 主演=" + m.getActors() + ", 时长=" + m.getDuration() + "分钟, 评分=" + m.getRating());
    }
    
    /**
     * 处理排片管理
     */
    private void handleScheduleManagement() {
        while (true) {
            System.out.println(Constants.SHORT_SEPARATOR_LINE);
            System.out.println("                排片管理");
            System.out.println(Constants.SHORT_SEPARATOR_LINE);
            System.out.println("1. 增加场次");
            System.out.println("2. 修改场次");
            System.out.println("3. 删除场次");
            System.out.println("4. 列出场次（当日/近3日/近7日）");
            System.out.println("5. 自动排片");
            System.out.println("0. 返回上级菜单");
            System.out.print("请选择操作：");
            String choice = scanner.nextLine().trim();
            try {
                switch (choice) {
                    case "1":
                        addScheduleFlow();
                        break;
                    case "2":
                        modifyScheduleFlow();
                        break;
                    case "3":
                        deleteScheduleFlow();
                        break;
                    case "4":
                        listSchedulesFlow();
                        break;
                    case "5":
                        autoScheduleFlow();
                        break;
                    case "0":
                        return;
                    default:
                        System.out.println(Constants.INVALID_INPUT);
                }
            } catch (Exception e) {
                System.out.println(Constants.OPERATION_FAILED + ": " + e.getMessage());
            }
        System.out.println();
        }
    }
    
    private void addScheduleFlow() {
        System.out.print("场次ID：");
        String sid = scanner.nextLine().trim();
        System.out.print("电影ID：");
        String mid = scanner.nextLine().trim();
        Movie movie = movieService.findById(mid);
        if (movie == null) {
            System.out.println("电影不存在");
            return;
        }
        System.out.print("放映厅ID（例如：" + Constants.GOLD_HALL_ID + "): ");
        String hallId = scanner.nextLine().trim();
        System.out.print("放映时间（" + Constants.DATE_TIME_FORMAT + "): ");
        LocalDateTime showTime = parseDateTime(scanner.nextLine().trim());
        System.out.print("票价（元）：");
        BigDecimal price = parseBigDecimal(scanner.nextLine().trim());
        Schedule s = new Schedule(sid, mid, hallId, showTime, price);
        scheduleService.addSchedule(s, movieService);
        System.out.println(Constants.SCHEDULE_ADDED);
    }
    
    private void modifyScheduleFlow() {
        System.out.print("请输入要修改的场次ID：");
        String sid = scanner.nextLine().trim();
        Schedule existing = scheduleService.findById(sid);
        if (existing == null) {
            System.out.println("场次不存在");
            return;
        }
        Movie oldMovie = movieService.findById(existing.getMovieId());
        String oldTitle = oldMovie == null ? "" : oldMovie.getTitle();
        System.out.print("新电影ID（留空不改）：");
        String mid = scanner.nextLine();
        System.out.print("新放映厅ID（留空不改）：");
        String hid = scanner.nextLine();
        System.out.print("新放映时间（" + Constants.DATE_TIME_FORMAT + "，留空不改）：");
        String timeStr = scanner.nextLine();
        System.out.print("新票价（留空不改）：");
        String priceStr = scanner.nextLine();
        String newMovieId = mid.trim().isEmpty() ? null : mid.trim();
        String newHallId = hid.trim().isEmpty() ? null : hid.trim();
        LocalDateTime newTime = timeStr.trim().isEmpty() ? null : parseDateTime(timeStr.trim());
        BigDecimal newPrice = priceStr.trim().isEmpty() ? null : parseBigDecimal(priceStr.trim());
        scheduleService.modifySchedule(sid, newMovieId, newHallId, newTime, newPrice, movieService);
        Movie newMovie = movieService.findById(scheduleService.findById(sid).getMovieId());
        String newTitle = newMovie == null ? "" : newMovie.getTitle();
        logService.writeLog("修改场次", currentUser.getUsername(), "时间=" + (newTime == null ? existing.getShowTime() : newTime) + ", 原片名=" + oldTitle + ", 新片名=" + newTitle);
        System.out.println(Constants.SCHEDULE_UPDATED);
    }
    
    private void deleteScheduleFlow() {
        System.out.print("请输入要删除的场次ID：");
        String sid = scanner.nextLine().trim();
        Schedule existing = scheduleService.findById(sid);
        if (existing == null) {
            System.out.println("场次不存在");
            return;
        }
        Movie movie = movieService.findById(existing.getMovieId());
        String title = movie == null ? "" : movie.getTitle();
        System.out.println("警告：删除后不可恢复！");
        System.out.print("确认删除场次 '" + title + "'，时间=" + existing.getShowTime() + " ? 输入Y确认：");
        String c = scanner.nextLine().trim();
        if (!"Y".equalsIgnoreCase(c)) {
            System.out.println("已取消删除");
            return;
        }
        scheduleService.deleteSchedule(sid);
        logService.writeLog("删除场次", currentUser.getUsername(), "时间=" + existing.getShowTime() + ", 片名=" + title);
        System.out.println(Constants.SCHEDULE_DELETED);
    }
    
    private void listSchedulesFlow() {
        System.out.println("选择范围：1-当日  2-近3日  3-近7日");
        String c = scanner.nextLine().trim();
        int days = "1".equals(c) ? 1 : ("2".equals(c) ? 3 : 7);
        List<Schedule> list = scheduleService.listByRangeDays(days);
        if (list.isEmpty()) System.out.println("暂无场次");
        for (Schedule s : list) printScheduleSummary(s);
    }
    
    private void autoScheduleFlow() {
        // 简单自动排片：未来3天的 19:00，为评分Top影片安排到固定厅
        List<Movie> showing = movieService.listShowing().stream()
                .sorted(Comparator.comparingDouble(Movie::getRating).reversed())
                .collect(Collectors.toList());
        if (showing.isEmpty()) {
            System.out.println("暂无在映影片，无法自动排片");
            return;
        }
        String[] halls = new String[]{Constants.GOLD_HALL_ID, Constants.SILVER_HALL_ID, Constants.DIAMOND_HALL_ID, Constants.RUBY_HALL_ID, Constants.JADE_HALL_ID};
        int scheduleCount = 0;
        for (int d = 0; d < 3; d++) {
            LocalDateTime time = LocalDate.now().plusDays(d).atTime(19, 0);
            int hi = 0;
            for (Movie m : showing) {
                if (hi >= halls.length) break;
                String sid = "SCH" + time.format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + "_" + (hi + 1);
                Schedule s = new Schedule(sid, m.getMovieId(), halls[hi], time, new BigDecimal("50"));
                try {
                    scheduleService.addSchedule(s, movieService);
                    scheduleCount++;
                } catch (Exception ignore) {
                    // 碰到冲突则跳过
                }
                hi++;
            }
        }
        System.out.println("自动排片完成，新增场次：" + scheduleCount);
    }
    
    private void printScheduleSummary(Schedule s) {
        Movie m = movieService.findById(s.getMovieId());
        String title = m == null ? s.getMovieId() : m.getTitle();
        System.out.println("场次ID=" + s.getScheduleId() + ", 片名=" + title + ", 厅=" + s.getHallId() + ", 时间=" + s.getShowTime() + ", 票价=" + s.getPrice() + ", 状态=" + s.getStatus());
    }
    
    /**
     * 处理销售数据查看
     */
    private void handleSalesDataView() {
        System.out.println("选择范围：1-当日  2-当周  3-当月");
        String c = scanner.nextLine().trim();
        LocalDateTime start;
        LocalDateTime end;
        LocalDate today = LocalDate.now();
        switch (c) {
            case "1":
                start = today.atStartOfDay();
                end = today.plusDays(1).atStartOfDay().minusSeconds(1);
                break;
            case "2":
                start = today.minusDays(today.getDayOfWeek().getValue() - 1).atStartOfDay();
                end = start.plusDays(7).minusSeconds(1);
                break;
            case "3":
                start = today.withDayOfMonth(1).atStartOfDay();
                end = start.plusMonths(1).minusSeconds(1);
                break;
            default:
                System.out.println(Constants.INVALID_INPUT);
                return;
        }
        var tickets = ticketService.getTicketsByDateRange(start, end);
        Map<String, List<com.cinema.model.Ticket>> bySchedule = tickets.stream().collect(Collectors.groupingBy(com.cinema.model.Ticket::getScheduleId));
        if (bySchedule.isEmpty()) {
            System.out.println("当前范围内暂无销售数据");
            return;
        }
        for (Map.Entry<String, List<com.cinema.model.Ticket>> e : bySchedule.entrySet()) {
            String sid = e.getKey();
            List<com.cinema.model.Ticket> list = e.getValue();
            int sold = (int) list.stream().filter(t -> t.getStatus() == com.cinema.model.TicketStatus.VALID || t.getStatus() == com.cinema.model.TicketStatus.USED).count();
            int refunded = (int) list.stream().filter(t -> t.getStatus() == com.cinema.model.TicketStatus.REFUNDED).count();
            BigDecimal totalFace = list.stream().map(com.cinema.model.Ticket::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal totalActual = list.stream().filter(t -> t.getStatus() != com.cinema.model.TicketStatus.REFUNDED).map(com.cinema.model.Ticket::getActualPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal refundAmount = list.stream().filter(t -> t.getStatus() == com.cinema.model.TicketStatus.REFUNDED).map(com.cinema.model.Ticket::getActualPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            Schedule s = scheduleService.findById(sid);
            String title = (s == null) ? sid : (movieService.findById(s.getMovieId()) == null ? s.getMovieId() : movieService.findById(s.getMovieId()).getTitle());
            System.out.println("[场次=" + sid + ", 片名=" + title + "] 销售票数=" + sold + ", 单价示例=" + (s == null ? "-" : s.getPrice()) + ", 退票数=" + refunded + ", 退票金额=" + refundAmount + ", 总票价(面值)=" + totalFace + ", 实收=" + totalActual);
        }
    }
    
    /**
     * 处理影片信息查看
     */
    private void handleMovieInfoView() {
        // 简版：列出所有在映影片
        for (Movie m : movieService.listShowing()) {
            printMovieSummary(m);
        }
        System.out.println();
    }
    
    /**
     * 处理场次信息查看
     */
    private void handleScheduleInfoView() {
        System.out.println("选择范围：1-当日  2-近3日  3-近7日");
        String c = scanner.nextLine().trim();
        int days = "1".equals(c) ? 1 : ("2".equals(c) ? 3 : 7);
        for (Schedule s : scheduleService.listByRangeDays(days)) {
            printScheduleSummary(s);
        }
        System.out.println();
    }
    
    /**
     * 处理座位信息查看
     */
    private void handleSeatInfoView() {
        // TODO: 实现座位信息查看功能
        System.out.println("座位信息查看功能正在开发中...");
        System.out.println();
    }
    
    /**
     * 处理售票
     */
    private void handleTicketSale() {
        System.out.print("请输入场次ID：");
        String sid = scanner.nextLine().trim();
        Schedule s = scheduleService.findById(sid);
        if (s == null) {
            System.out.println("场次不存在");
            System.out.println();
            return;
        }
        System.out.print("输入选座（格式：row,col;row,col 支持多个；例如 3,5;3,6;3,7）：");
        String sel = scanner.nextLine().trim();
        List<com.cinema.model.SeatSelection> selections = new ArrayList<>();
        if (!sel.isEmpty()) {
            for (String part : sel.split(";")) {
                String[] rc = part.trim().split(",");
                if (rc.length == 2) {
                    selections.add(new com.cinema.model.SeatSelection(Integer.parseInt(rc[0].trim()), Integer.parseInt(rc[1].trim())));
                }
            }
        }
        if (selections.isEmpty()) {
            System.out.println("未选择座位");
            System.out.println();
            return;
        }
        // 简易折扣：早上10点场9折
        BigDecimal discount = (s.getShowTime().getHour() <= 10) ? new BigDecimal("0.9") : null;
        List<com.cinema.model.Ticket> tickets = ticketService.sellBatch(sid, s.getHallId(), selections, s.getPrice(), discount);
        BigDecimal pay = tickets.stream().map(com.cinema.model.Ticket::getActualPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        System.out.println("应付金额：" + pay);
        for (com.cinema.model.Ticket t : tickets) {
            Movie m = movieService.findById(s.getMovieId());
            System.out.println("票据：片名=" + (m == null ? s.getMovieId() : m.getTitle()) + ", 场次=" + sid + ", 座位=" + t.getSeatId() + ", 票号=" + t.getTicketId());
        }
        System.out.println();
    }
    
    /**
     * 处理退票
     */
    private void handleTicketRefund() {
        System.out.print("请输入电子票号：");
        String tid = scanner.nextLine().trim();
        // 放映前1小时允许退票
        com.cinema.model.Ticket target = ticketService.all().stream().filter(t -> t.getTicketId().equals(tid)).findFirst().orElse(null);
        if (target == null) {
            System.out.println("未找到票据");
            System.out.println();
            return;
        }
        Schedule s = scheduleService.findById(target.getScheduleId());
        if (s == null) {
            System.out.println("关联场次不存在");
            System.out.println();
            return;
        }
        long minutes = java.time.Duration.between(java.time.LocalDateTime.now(), s.getShowTime()).toMinutes();
        if (minutes < 60) {
            System.out.println("距离开场不足1小时，不可退票");
            System.out.println();
            return;
        }
        boolean ok = ticketService.refundByTicketId(tid);
        System.out.println(ok ? Constants.TICKET_REFUNDED : Constants.OPERATION_FAILED);
        System.out.println();
    }
    
    private void handleSeatMapView() {
        System.out.print("请输入片名：");
        String title = scanner.nextLine().trim();
        List<Movie> movies = movieService.query(emptyToNull(title), null, null);
        if (movies.isEmpty()) {
            System.out.println("未找到影片");
            return;
        }
        Movie movie = movies.get(0);
        System.out.print("请输入场次ID：");
        String sid = scanner.nextLine().trim();
        Schedule s = scheduleService.findById(sid);
        if (s == null || !movie.getMovieId().equals(s.getMovieId())) {
            System.out.println("场次不存在或不属于该影片");
            return;
        }
        com.cinema.model.CinemaHall hall = this.hallService.getHallById(s.getHallId());
        if (hall == null) {
            System.out.println("放映厅不存在");
            return;
        }
        printSeatMap(hall);
    }

    private void printSeatMap(com.cinema.model.CinemaHall hall) {
        int rows = hall.getRows();
        int cols = hall.getSeatsPerRow();
        int total = hall.getTotalSeats();
        int available = hall.getAvailableSeats();
        int occupied = total - available;
        System.out.println("总座位数=" + total + ", 空闲座位数=" + available + ", 已占用=" + occupied);
        System.out.print("   ");
        for (int c = 1; c <= cols; c++) {
            System.out.print(c + "\t");
        }
        System.out.println();
        for (int r = 1; r <= rows; r++) {
            System.out.print(r + "\t");
            for (int c = 1; c <= cols; c++) {
                com.cinema.model.Seat seat = hall.getSeat(r, c);
                System.out.print((seat != null && seat.isAvailable() ? "O" : "X") + "\t");
            }
            System.out.println();
        }
    }
    
    private int parseInt(String text, String err) {
        try { return Integer.parseInt(text); } catch (Exception e) { throw new IllegalArgumentException(err); }
    }
    
    private double parseDouble(String text, String err) {
        try { return Double.parseDouble(text); } catch (Exception e) { throw new IllegalArgumentException(err); }
    }
    
    private BigDecimal parseBigDecimal(String text) {
        try { return new BigDecimal(text); } catch (Exception e) { throw new IllegalArgumentException("金额格式不正确"); }
    }
    
    private LocalDateTime parseDateTime(String text) {
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern(Constants.DATE_TIME_FORMAT);
        try { return LocalDateTime.parse(text, fmt); } catch (Exception e) { throw new IllegalArgumentException("时间格式应为：" + Constants.DATE_TIME_FORMAT); }
    }
    
    private String emptyToNull(String s) {
        return s == null || s.trim().isEmpty() ? null : s.trim();
    }
} 